/*
 * Copyright Owen Watson 2009
 * 
 * This file is part of ArtNotes.
 *
 * ArtNotes is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.

 * ArtNotes is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with ArtNotes.  If not, see <http://www.gnu.org/licenses/>.
*/

using System;
using System.Drawing;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using MonoTouch.CoreGraphics;

namespace ArtNotes
{

	/// <summary>
	/// Provides a library for prefoming common
	/// operations on images used throughout the
	/// application.
	/// </summary>
	public class ANImageUtils
	{

		public ANImageUtils ()
		{
		}
		
		/// <summary>
		/// Overlays a polaroid frame onto an
		/// existing image. Optomised for 75x75 px
		/// </summary>
		/// <param name="image">
		/// Base Image
		/// </param>
		/// <param name="overlay">
		/// Overlay Image (should be a polaroid frame)
		/// </param>
		/// <param name="imageRect">
		/// Size of base image
		/// </param>
		/// <param name="overlayRect">
		/// Size of overlay image
		/// </param>
		/// <param name="size">
		/// Target size
		/// </param>
		/// <returns>
		/// Returns a composite image in
		/// the form of a polaroid.
		/// </returns>
		public UIImage overlayImageWithPolaroid (UIImage image, UIImage overlay, RectangleF imageRect, RectangleF overlayRect, SizeF size)
		{
			RectangleF imageRectAdjusted = imageRect;
			imageRectAdjusted.Width -= 5f;
			imageRectAdjusted.Y += 5f;
			UIImage img;
			img = overlayImage (image,overlay,imageRectAdjusted,overlayRect,size);
			return img;
		}
		
		/// <summary>
		/// Resizes an image, ignoring proportions
		/// </summary>
		/// <param name="image">
		/// Base image
		/// </param>
		/// <param name="size">
		/// Desired size
		/// </param>
		/// <returns>
		/// Resized image
		/// </returns>
		public UIImage resizeImage(UIImage image, SizeF size)
		{
			UIImage resizedImage;
			UIGraphics.BeginImageContext(size);
			
			CGContext context = UIGraphics.GetCurrentContext();
			context.TranslateCTM(0.0f,size.Height);
			context.ScaleCTM(1.0f, -1.0f);
			context.DrawImage(new RectangleF(0,0,size.Width,size.Height),image.CGImage);
			
			resizedImage = UIGraphics.GetImageFromCurrentImageContext();
			UIGraphics.EndImageContext();
			return resizedImage;
		}
		
		/// <summary>
		/// Scales an image, ensuring the maximum
		/// height and / or width are not exceeded.
		/// </summary>
		/// <param name="image">
		/// Base image
		/// </param>
		/// <param name="maxWidth">
		/// Maximum height
		/// </param>
		/// <param name="maxHeight">
		/// Maximum width
		/// </param>
		/// <returns>
		/// Scaled image
		/// </returns>
		public UIImage scaleImage(UIImage image, float maxWidth, float maxHeight)
		{
			float imageWidth = image.Size.Width;
			float imageHeight = image.Size.Height;
			
			float scaleFactor = 0;
			float targetHeight = 0;
			float targetWidth = 0;
			
			scaleFactor = imageWidth / maxWidth;
			
			targetHeight = imageHeight / scaleFactor;
			targetWidth = imageWidth / scaleFactor;
			
			if(targetHeight > maxHeight)
			{
				scaleFactor = targetHeight / maxHeight;
				targetHeight = targetHeight / scaleFactor;
				targetWidth = targetWidth / scaleFactor;
			}
			
			return scaleImage(image, new SizeF(targetWidth, targetHeight));
		}
		
		/// <summary>
		/// Scales an image to the provided size
		/// </summary>
		/// <param name="image">
		/// Base Image
		/// </param>
		/// <param name="size">
		/// Desired Size
		/// </param>
		/// <returns>
		/// Scaled image
		/// </returns>
		public UIImage scaleImage(UIImage image, SizeF size)
		{
			UIGraphics.BeginImageContext(size);
			
			image.Draw(new RectangleF(new PointF(0,0),size));
			
			UIImage scaledImage = UIGraphics.GetImageFromCurrentImageContext();
			UIGraphics.EndImageContext();
			
			return scaledImage;
		}
		
		/// <summary>
		/// Overlays two images, taking into account transparency.
		/// 
		/// Adapted from Obj-C at http://www.realdevelopers.com/blog/?p=415
		/// </summary>
		/// <param name="image">
		/// Base image
		/// </param>
		/// <param name="overlay">
		/// Image to overlay onto the base image
		/// </param>
		/// <param name="imageRect">
		/// Size of the base image
		/// </param>
		/// <param name="overlayRect">
		/// Size of the image to overlay
		/// </param>
		/// <param name="size">
		/// Desired size
		/// </param>
		/// <returns>
		/// Composited image
		/// </returns>
		public UIImage overlayImage (UIImage image, UIImage overlay, RectangleF imageRect, RectangleF overlayRect, SizeF size)
		{
			RectangleF imageBoundingBox = imageRect;
			RectangleF overlayBoundingBox = overlayRect;
			
			
			CGBitmapContext context = createBitmapOfSize (size);
			
			//context.SetRGBFillColor (1, 1, 1, 1);
			//context.FillRect (imageBoundingBox);
			
			context.ClearRect (imageBoundingBox);
			
			context.DrawImage (imageBoundingBox, image.CGImage);
			context.DrawImage (overlayBoundingBox, overlay.CGImage);
			
			context.SetAllowsAntialiasing (true);
			context.SetShouldAntialias (true);
			
			UIImage result = UIImage.FromImage (context.ToImage ());
			return result;
		}
		
		/// <summary>
		/// Creates a new bitmap context of the size specified
		/// enabling antialiasing (although this doesn't seem
		/// to have any effect)
		/// 
		/// Adapted from Obj-C at http://www.realdevelopers.com/blog/?p=415
		/// </summary>
		/// <param name="size">
		/// Desired size
		/// </param>
		/// <returns>
		/// A <see cref="CGBitmapContext"/>
		/// </returns>
		private CGBitmapContext createBitmapOfSize (SizeF size)
		{
			CGColorSpace colorspace;
			int bitmapBytesPerRow;
			
			bitmapBytesPerRow = (int)(size.Width * 4);
			colorspace = CGColorSpace.CreateDeviceRGB ();
			
			CGBitmapContext context = new CGBitmapContext (
					IntPtr.Zero,
					(int)size.Width,
					(int)size.Height,
					8,
					bitmapBytesPerRow,
					colorspace,
					CGImageAlphaInfo.PremultipliedLast
				);
			
			context.SetAllowsAntialiasing (true);
			context.SetShouldAntialias (true);
			
			return context;
		}
	}
}
